Conventional digital computers execute tasks by executing sequences of related instructions that access or modify the contents of a set of registers and memory cells. Occasionally, during execution of a sequence of instructions an exception occurs, such as an interrupt or operating system calls (traps), which requires the operating system to immediately respond. A processor may receive exceptions from a number of sources, including translation lookaside buffer (TLB) misses, arithmetic overflows, and I/O interrupts. Conventionally, when an exception is detected, the normal sequence of instructions is suspended while the processor deals with the exception. The use of exceptions and exception processing is well known in the art of computer architecture.
FIG. 1 is a flow chart 10 of processing an exception in a conventional manner. As shown in FIG. 1, when an exception is asserted (block 12) the exception is decoded and execution diverted (using an exception “vector”) to a new location that is designated for handling exceptions (block 14). The processor and/or system software must determine the priority of the exception (block 16) particularly if there are multiple exceptions, in which case the highest priority must be dealt with first. The execution of the original task is suspended and the key processor “state” information must be preserved in main memory (block 18) so that once the exception is serviced, the original task may be resumed. The exception is then serviced (block 20). After the exception is serviced, the processor must restore the original “state” information that was earlier preserved (block 22). The execution of the original task is then resumed (block 24).
Typically, in an embedded real-time system, a number of exceptions, with varying levels of importance, i.e., priority, must be managed. As can be seen in FIG. 1, decoding the exception, determining priority, and preserving the state of the system, present a large amount of overhead in servicing exceptions.
One conventional strategy implemented in processors to speed operation, typically when handling multiple exceptions, is called “nesting”. To reduce the amount of time spent in prioritization of multiple interrupts, a processor may use a fixed set of priorities. When a higher priority interrupt is signaled (higher than the current executing program), the processor suspends execution and automatically preserves the entire processor state into an area of memory referred to as the “stack”. Unfortunately, as processors have developed, the amount of state information has grown such that saving all processor state, regardless of need, is an undue burden. Consequently, stacking in current processors actually degrades performance due to the amount of state information that must be stacked.
Another technique employed to service exceptions includes register windows, which help minimize the time spent doing “context switching.” In a register window approach, windows are made available by periodically allocating a set of registers from a larger physical set when a subroutine is called or an exception is signaled. Unfortunately, depending on the number of physical registers and the program, register “spills” may occur during which there are not enough registers to handle the exception. Consequently, prior windows have to be written into main memory to create a new window resulting in a degradation in the performance.
Thus, what is needed is a technique to minimize the overhead associated with servicing an exception to speed the handling of exceptions and to separate especially critical exceptions from normal priority exceptions.